package asava.sources;

import asava.names.Name;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author Tim Richter
 */
public final class SourcePath {
    private static final String SUFFIX = ".java";

    private final File root;
    private final Set<String> packages;
    private final Map<String, Source> sourceMap;

    public SourcePath(final String path) {
        this(new File(path));
    }

    public SourcePath(final File root) {
        this.root = root;
        this.packages = new HashSet<>();
        this.sourceMap = new HashMap<>();

        if (!root.isDirectory()) {
            throw new IllegalArgumentException("root must be a directory");
        } else {
            for (final File f : root.listFiles()) {
                init(f);
            }
        }
    }

    public Source findSource(final Name name) {
        return sourceMap.get(name.value);
    }

    public boolean containsPackage(final Name name) {
        return packages.contains(name.value);
    }

    public boolean containsSource(final Name name) {
        return sourceMap.containsKey(name.value);
    }

    private void init(final File file) {
        if (file.isDirectory()) {
            for (final File f : file.listFiles()) {
                init(f);
            }
            packages.add(internalPackageName(file.getPath()));
        } else if (file.isFile() && file.getPath().endsWith(SUFFIX)) {
            sourceMap.put(internalClassName(file.getPath()), new Source(file));
        }
    }

    private String internalPackageName(final String fileName) {
        return dotify(fileName.substring(root.getPath().length() + 1));
    }

    private String internalClassName(final String fileName) {
        return dotify(fileName.substring(root.getPath().length() + 1, fileName.length() - 5));
    }

    private String dotify(final String fileName) {
        return fileName.replace(File.separatorChar, '.');
    }
}
